package cn.datawin.cmppclient.sender.handler;

import cn.datawin.cmppclient.sender.entity.SessionStatus;
import cn.datawin.cmppclient.sender.env.NetwayEnv;
import cn.datawin.cmppclient.sender.thread.CommonThreadPoolFactory;
import cn.datawin.cmppclient.sender.util.SMSUtil;
import cn.datawin.sms.cmpp2.InboxLog;
import cn.datawin.sms.cmpp2.ReportLog;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.drondea.sms.channel.ChannelSession;
import com.drondea.sms.common.util.CommonUtil;
import com.drondea.sms.message.cmpp.CmppDeliverRequestMessage;
import com.drondea.sms.message.cmpp.CmppDeliverResponseMessage;
import com.drondea.sms.message.cmpp.CmppReportRequestMessage;
import com.drondea.sms.session.AbstractClientSessionManager;
import com.drondea.sms.type.DefaultEventGroupFactory;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.EventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.ScheduledExecutorService;

/**
 * cmpp的客户端收到回执消息和MO业务处理
 **/
@Slf4j
@Component
@ChannelHandler.Sharable
public class CmppClientBusinessHandler  extends ChannelDuplexHandler {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof CmppDeliverRequestMessage dp) {
			ChannelSession channelSession = CommonUtil.getChannelSession(ctx.channel());
            CommonThreadPoolFactory.getInstance().getBizPoolExecutor().submit(() -> {
                try {
                    // 状态报告
                    if (dp.isReport()) {
                        doReport(channelSession, dp);
                    } else {
                        if (dp.isMsgComplete()) {
                            doMo(channelSession, dp);
                        }
                    }
                } catch (Exception e) {
                    log.error("deliver 出错了：" + e.getMessage(), e);
                }

            });
            responseDeliver(channelSession, dp);
            return;
        }
        super.channelRead(ctx, msg);
    }

    /**
     * 响应回执
     *
     * @param channelSession
     * @param dp
     */
    protected void responseDeliver(ChannelSession channelSession, CmppDeliverRequestMessage dp) {
        CmppDeliverResponseMessage responseMessage = new CmppDeliverResponseMessage(dp.getHeader());
        responseMessage.setResult(0);
        responseMessage.setMsgId(dp.getMsgId());

		//放到netty中发送，在用户线程中发送有问题
		if (!channelSession.getChannel().isActive()) {
			return;
		}
		EventExecutor executor = channelSession.getChannel().pipeline().firstContext().executor();
		executor.submit(() -> {
			channelSession.sendMessage(responseMessage);
		});
	}
    // 处理MO
    private void doMo(ChannelSession channelSession, CmppDeliverRequestMessage dp) {
//        log.debug("doMo={}", dp.toString());
        InboxLog inboxLog = new InboxLog();
        inboxLog.setChannelNo(channelSession.getConfiguration().getId());
        inboxLog.setContent(dp.getMsgContent());
        inboxLog.setSpNumber(dp.getDestId());
        inboxLog.setPhoneNo(dp.getSrcTerminalId());
        inboxLog.setCreateDate(new Date());
        inboxLog.setCharset(SMSUtil.getCharsetByByte(dp.getMsgFmt().getValue()));//编码
        inboxLog.setPrMsgId(dp.getMsgId().toString());
        String inboxLogStr = JSON.toJSONString(inboxLog);
        log.debug("inboxLog,{}", JSON.toJSONString(inboxLog));
		//TODO 发送inboxLog到队列中

//        SpringContextUtil.getBean(ProducerService.class).sendMessage(RocketMqCommonTopic.SMS_CMPP_INBOX_TOPIC, inboxLogStr);

    }

    /**
     * 长短信也会有多条状态报告
     *
     * @param dp
     */
    private void doReport(ChannelSession channelSession, CmppDeliverRequestMessage dp) {
        log.debug("doReport={}", dp.toString());

        CmppReportRequestMessage reportMessage = dp.getReportRequestMessage();
        ReportLog reportLog = new ReportLog();
        reportLog.setPrMsgId(reportMessage.getMsgId().toString());
        reportLog.setDestId(dp.getDestId());
        reportLog.setStat(reportMessage.getStat());
        reportLog.setSubmitTime(reportMessage.getSubmitTime());
        reportLog.setDoneTime(reportMessage.getDoneTime());
        reportLog.setPhoneNo(reportMessage.getDestterminalId());
        reportLog.setCreateDate(new Date());
        reportLog.setProviderNo(channelSession.getConfiguration().getId());

        reportLog.setDMsgId(dp.getMsgId().toString());
        reportLog.setDSeq(dp.getSequenceId());
        log.debug("reportLog,client,{}", JSON.toJSONString(reportLog));
//        log.debug("reportLog={}", JSON.toJSONString(reportLog));
		//TODO 发送reportLog到队列中

//        SpringContextUtil.getBean(ProducerService.class).sendMessage(RocketMqCommonTopic.SMS_CMPP_REPORT_TOPIC, JSON.toJSONString(reportLog));

//        String id = channelSession.getConfiguration().getId();
//        Channel channel = DatabaseCache.getChannelCachedByNo(id);
//        ReportWrap reportWrap = new ReportWrap(dp, channel);
//        reportWrap.saveReport(5);
        // TODO: 2022/11/29

    }


	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		if (evt == (Integer) ChannelSession.STATE_LOGIN_SUCCESS) {
			ChannelSession channelSession = CommonUtil.getChannelSession(ctx.channel());
			String channelId = channelSession.getConfiguration().getId();
			ScheduledExecutorService executor = DefaultEventGroupFactory.getInstance().getScheduleExecutor();
			executor.submit(() -> {
				modifySessionStatus(SessionStatus.LOGIN_COMPLETE, channelId);
			});
		}
		super.userEventTriggered(ctx, evt);
	}

	/**
	 * @param status
	 * @author volcano
	 * @date 2019年9月28日上午2:08:00
	 * @version V1.0
	 */
	public void modifySessionStatus(SessionStatus status, String no) {
		modifySessionStatus(status.name(), no);
	}

	public void modifySessionStatus(String status, String no) {
		if (status.equalsIgnoreCase(SessionStatus.MAX_CHANNELS_ERROR.toString())
				|| status.equalsIgnoreCase(SessionStatus.LOGIN_SUCCESS.toString())) {
			return;
		}
		AbstractClientSessionManager clientManager = SpringUtil.getBean(NetwayEnv.class).getClientManager(no);
		int connectedNum = 0;
		if (clientManager != null) {
			connectedNum = clientManager.getSessionSize();
		}

		// TODO: 2022/12/2
		//登录失败更新状态

//        IChannelDAO<?> dao = ApplicationContextUtil.getBean("channelExtDAO");
//        Channel updateSessionStatus = new Channel();
//        Channel channel = DatabaseCache.getChannelCachedByNo(no);
//        updateSessionStatus.setId(channel.getId());
//        updateSessionStatus.setSession_Status(String.format("(%1$s)%2$s", connectedNum, status));
//        updateSessionStatus.setSession_Status_Date(new Date());
//        dao.updateByPrimaryKeySelective(updateSessionStatus);
		// 通道登录日志保存
//        SystemLogUtil.getInstance().saveLog(channel, status);
	}

}
